package com.hjq.base.http.glide

import com.bumptech.glide.Priority
import com.bumptech.glide.load.DataSource
import com.bumptech.glide.load.HttpException
import com.bumptech.glide.load.data.DataFetcher
import com.bumptech.glide.load.model.GlideUrl
import com.bumptech.glide.util.ContentLengthInputStream
import com.bumptech.glide.util.Preconditions
import okhttp3.*
import java.io.IOException
import java.io.InputStream

/**
 * author : Android 轮子哥
 * github : https://github.com/getActivity/AndroidProject
 * time   : 2019/12/15
 * desc   : OkHttp 加载器
 */
class OkHttpFetcher internal constructor(factory: Call.Factory, url: GlideUrl) :
    DataFetcher<InputStream>, Callback {
    private val mCallFactory: Call.Factory = factory
    private val mGlideUrl: GlideUrl = url
    private var mInputStream: InputStream? = null
    private var mResponseBody: ResponseBody? = null
    private var mDataCallback: DataFetcher.DataCallback<in InputStream>? = null

    @Volatile
    private var mCall: Call? = null
    override fun loadData(
        priority: Priority,
        callback: DataFetcher.DataCallback<in InputStream>
    ) {
        val requestBuilder: Request.Builder = Request.Builder().url(mGlideUrl.toStringUrl())
        for ((key, value) in mGlideUrl.headers) {
            requestBuilder.addHeader(key, value)
        }
        val request: Request = requestBuilder.build()
        mDataCallback = callback
        mCall = mCallFactory.newCall(request)
        mCall!!.enqueue(this)
    }

    override fun onFailure(call: Call, e: IOException) {
        mDataCallback!!.onLoadFailed(e)
    }

    override fun onResponse(call: Call, response: Response) {
        mResponseBody = response.body
        if (response.isSuccessful) {
            val contentLength = Preconditions.checkNotNull(mResponseBody).contentLength()
            mInputStream =
                ContentLengthInputStream.obtain(mResponseBody!!.byteStream(), contentLength)
            mDataCallback!!.onDataReady(mInputStream)
        } else {
            mDataCallback!!.onLoadFailed(HttpException(response.message, response.code))
        }
    }

    override fun cleanup() {
        try {
            if (mInputStream != null) {
                mInputStream!!.close()
            }
        } catch (ignored: IOException) {
        }
        if (mResponseBody != null) {
            mResponseBody!!.close()
        }
        mDataCallback = null
    }

    override fun cancel() {
        if (mCall != null) {
            mCall!!.cancel()
        }
    }

    override fun getDataClass(): Class<InputStream> {
        return InputStream::class.java
    }

    override fun getDataSource(): DataSource {
        return DataSource.REMOTE
    }

}